﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Collections;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

namespace CommLink
{
    /// <summary>
    /// Communication link implementation wrapping CCS integrated dll functionality.
    /// </summary>
    public class CCSIntegratedDLLWrapper : CommLinkAbstract
    {
        /// <summary>
        /// Garbage collector handle - for pinning the callback provided to the CCS integrated dll
        /// </summary>
        GCHandle gch = new GCHandle();

        /// <summary>
        /// DLL initialization function.
        /// </summary>
        /// <param name="pOnReceiveCallback">Callback delegate for dll's message receive routine</param>
        /// <returns>Success status</returns>
        [DllImport("C:\\CCStudio_v3.3\\drivers\\omap4_sim_ua_releases\\omap4\\tisim_sensor_tb.dll")]
        public static extern int sensor_tb_init_custom(OnMessageReceiveCallback pOnReceiveCallback);

        /// <summary>
        /// DLL function to send a message.
        /// </summary>
        /// <param name="pOutData">Pointer to message data memory</param>
        /// <param name="nDataLen">Message data length</param>
        /// <returns>Success status</returns>
        [DllImport("C:\\CCStudio_v3.3\\drivers\\omap4_sim_ua_releases\\omap4\\tisim_sensor_tb.dll")]
        public static extern int sensor_tb_send_cmd(IntPtr pOutData, int nDataLen);

        /// <summary>
        /// Callback function invoked when underlying driver has received a message
        /// </summary>
        /// <param name="pInData">Pointer to message data memory</param>
        /// <param name="nDataLen">Message data's length</param>
        /// <returns>Success status</returns>
        public delegate int OnMessageReceiveCallback(IntPtr pInData, int nDataLen);

        /// <summary>
        /// Message received event providing the byte array data received from the dll.
        /// </summary>
        public override event MessageReceived OnMessageReceived;

        /// <summary>
        /// Callback provided to the CCS integrated dll for new message notification.
        /// </summary>
        /// <param name="pInData">Pointer to the message data memory</param>
        /// <param name="nDataLen">Message data length</param>
        /// <returns>Error status</returns>
        int messageReceiveCallback(IntPtr pInData, int nDataLen)
        {
            if (OnMessageReceived != null)
            {
                byte[] OutData = new byte[nDataLen];
                try
                {
                    Marshal.Copy(pInData, OutData, 0, nDataLen);
                    OnMessageReceived(OutData);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            return 0;
        }

        /// <summary>
        /// Sends a data buffer trough CCS integrated sensor tb dll
        /// </summary>
        /// <param name="OutData">Byte array to sned</param>
        /// <returns>Error status</returns>
        public override int messageSend(byte[] OutData)
        {
            int status = 0;
            IntPtr pOutBuf = (IntPtr)null;
            try
            {
                pOutBuf = Marshal.AllocHGlobal(OutData.Length);
                Marshal.Copy(OutData, 0, pOutBuf, OutData.Length);
                status = sensor_tb_send_cmd(pOutBuf, OutData.Length);
            }
            catch (Exception ex)
            {
                status = -1;
                MessageBox.Show(ex.Message);
            }
            finally
            {
                if (pOutBuf != (IntPtr)null)
                    Marshal.FreeHGlobal(pOutBuf);
            }
            return status;
        }

        /// <summary>
        /// Public constructor
        /// </summary>
        public CCSIntegratedDLLWrapper()
        {
            int status = 1;
            OnMessageReceiveCallback callback = new OnMessageReceiveCallback(messageReceiveCallback);
            gch = GCHandle.Alloc(callback);
            try
            {
                status = sensor_tb_init_custom(callback);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                status = 0;
            }

            if (status == 0)
            {
                if (gch.IsAllocated)
                    gch.Free();
            }
        }

        /// <summary>
        /// Destructor freeing the callback function for garbage collecting
        /// </summary>
        ~CCSIntegratedDLLWrapper()
        {
            if (gch.IsAllocated)
                gch.Free();
        }

        /// <summary>
        /// Closes up anyform of open comm channels
        /// </summary>
        public override void closeConnection()
        {
            if (OnConnectionStatusChange != null)
                OnConnectionStatusChange(ConnectionStates.NotConnected);
        }

        /// <summary>
        /// Connection status change event.
        /// </summary>
        public override event ConnectionStatusChange OnConnectionStatusChange;

        /// <summary>
        /// Opens communication channels
        /// </summary>
        public override void openConnection()
        {
            if (OnConnectionStatusChange != null)
                OnConnectionStatusChange(ConnectionStates.Connected);
        }

        /// <summary>
        /// Returns connection type name
        /// </summary>
        /// <returns>Connection type name</returns>
        public override string getName()
        {
            return "CCS integrated dll (obsolete)";
        }
    }
}
